package com.example.springboottools.gms;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.bind.DateTypeAdapter;
import com.google.gson.internal.bind.util.ISO8601Utils;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;

public class Helper {
    private static Logger logger = LoggerFactory.getLogger(Helper.class);
    private static Gson gson = new GsonBuilder()
            .registerTypeAdapter(Date.class, new DateTypeAdapter())  // 默认适配器
            .registerTypeAdapter(Date.class, new CustomDateAdapter(2, 2, Locale.CHINESE))  // yyyy-MM-dd HH:mm:ss
            .registerTypeAdapter(Date.class, new CustomDateAdapter(2, 3, Locale.CHINESE))
            //.registerTypeAdapter(Date.class, new CustomDateAdapter(0, 0, Locale.CHINESE))  // 2020年11月2日 星期一 上午10时54分01秒 CST
            //.registerTypeAdapter(Date.class, new CustomDateAdapter(0, 1, Locale.CHINESE))  // 2020年11月2日 星期一 上午10时54分34秒
            //.registerTypeAdapter(Date.class, new CustomDateAdapter(0, 3, Locale.CHINESE))  // 2020年11月2日 星期一 上午10:55
            //.registerTypeAdapter(Date.class, new CustomDateAdapter(1, 1, Locale.CHINESE))  // 2020年11月2日 上午11时00分58秒
            //.registerTypeAdapter(Date.class, new CustomDateAdapter(1, 2, Locale.CHINESE))  // 2020年11月2日 10:56:01
            //.registerTypeAdapter(Date.class, new CustomDateAdapter(3, 2, Locale.CHINESE))  // 20-11-2 10:56:29
            //.registerTypeAdapter(Date.class, new CustomDateAdapter(2, 2, Locale.ENGLISH))  // Nov 2, 2020 10:46:51 AM
            .registerTypeAdapter(Date.class, new CustomDateAdapter(2, 2, Locale.US))       // Nov 2, 2020 10:46:51 AM
            //.registerTypeAdapter(Date.class, new CustomDateAdapter(2, 2, Locale.getDefault())) // 根据服务器不一样而不一样
            .create();

    /***
     * 获取程序报错信息 by lyx on 2020-09-08
     * @param e
     * @return
     */
    public static String getExceptionInfo(Exception e) {
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        e.printStackTrace(new PrintStream(bos));
        byte[] bit=bos.toByteArray();
        String error=new String(bit).replaceAll("\\$", "");
        return error;
    }

    /***
     * 获取程序报错信息 by lyx on 2020-09-08
     * @param e
     * @return
     */
    public static String getExceptionInfo(Throwable e) {
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        e.printStackTrace(new PrintStream(bos));
        byte[] bit=bos.toByteArray();
        String error=new String(bit).replaceAll("\\$", "");
        return error;
    }

    /**
     * 产生新的uuid
     *
     * @return
     */
    public static String getUUID() {
        String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
        return uuid;
    }

    /**
     * 将null转化为""字符串
     *
     * @param obj
     * @return String
     */
    public static String toString(Object obj) {
        return obj == null ? "" : obj.toString();
    }

    public static Integer toNumber(String str){
        try{
            return Integer.parseInt(str);
        }catch (Exception e){
            System.out.println("Helper.toNumber错误：str为空或者不是数字！");
            return 0;
        }
    }
    public static Integer toNumber(Integer num){
        return num == null ? 0 : num;
    }
    public static Long toNumber(Long num){
        return num == null ? 0 : num;
    }


    public static <T> T getClaaesJson(String json, Class<T> t){
        return gson.fromJson(json,t);
    }

    static class CustomDateAdapter extends TypeAdapter<Date> {

        private final List<DateFormat> dateFormats = new ArrayList<>();

        /**
         * Creates a DateFormat with the given time and/or date style in the given
         * locale.
         * @param timeStyle a value from 0 to 3 indicating the time format,
         * ignored if flags is 2
         * @param dateStyle a value from 0 to 3 indicating the time format,
         * ignored if flags is 1
         * @param aLocale the locale for the format
         */
        public CustomDateAdapter(int dateStyle, int timeStyle, Locale aLocale) {
            this.dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle, aLocale));
        }

        public Date read(JsonReader in) throws IOException {
            if (in.peek() == JsonToken.NULL) {
                in.nextNull();
                return null;
            } else {
                return this.deserializeToDate(in.nextString());
            }
        }

        private synchronized Date deserializeToDate(String json) {
            for (DateFormat dateFormat : this.dateFormats) {
                try {
                    return dateFormat.parse(json);
                } catch (ParseException ignored) {
                }
            }

            try {
                return ISO8601Utils.parse(json, new ParsePosition(0));
            } catch (ParseException var5) {
                throw new JsonSyntaxException(json, var5);
            }
        }

        public synchronized void write(JsonWriter out, Date value) throws IOException {
            if (value == null) {
                out.nullValue();
            } else {
                String dateFormatAsString = this.dateFormats.get(0).format(value);
                out.value(dateFormatAsString);
            }
        }
    }



    public static Date StringToDate(String strDate, String reg) {
        SimpleDateFormat sdf = new SimpleDateFormat(reg);

        Date date = null;
        if (!isEmpty(strDate)) {
            try {
                date = sdf.parse(strDate);
            } catch (ParseException e) {
                logger.error("",e);
            }
        }
        return date;
    }

    public static Double toDouble(Number number) {
        if (number == null) {
            return null;
        }
        return Double.valueOf(number.doubleValue());
    }
    /**
     * 检查这个字符串是不是空字符串。
     *
     * @param chkStr
     * @return boolean
     */
    public static boolean isEmpty(String chkStr) {
        if (chkStr == null) {
            return true;
        } else {
            return "".equals(chkStr.trim()) ? true : false;
        }
    }
    public static Date stringToDate(String value) {
        DateFormat df = DateFormat.getDateInstance();
        Date date = null;
        if (!isEmpty(value)) {
            try {
                date = df.parse(value);
            } catch (ParseException e) {
                logger.info("", e);
            }
        }
        return date;
    }
    // build serial no-- copy from old code (framework-system-3.0.0.jar)

    // t1为空时，返回t2 by lyx on 2021-07-11
    public static <T> T nvl(T t1,T t2){
        return t1 == null ? t2:t1;
    }

    // str1为空时，返回str2 by lyx on 22021-12-22
    public static String nvlStr(String str1, String str2){
        return Helper.isEmpty(str1) ? str2:str1;
    }

}
